/*
 * Copyright (C) 2007 Anindya Chatterjee
 * This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.

 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *  to contact me mail me @ : anidotnet@gmail.com
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace SLS.ExClassLib.DataType
{

    /// <summary>Represents a Priority-Queue that are sorted by key
    /// <para>based on the associated <see cref="T:System.Collections.Generic.IComparer"></see> implementation.
    /// <para>Data are entered in a <see cref="T:System.Collections.Queue"></see> and sorted by the associated keys.
    /// <para>Data of highest priority are popped from the top.</para></para></para>
    /// </summary>
    [Serializable, DebuggerDisplay("Count = {Count}"), ComVisible(false)]
    public class PriorityQueue<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, ICollection, IEnumerable
    {

        #region Constructors
        public bool sortl2h = false;
        static PriorityQueue()
        {
            // initializes two empty queues for value and key
            // these two arrays are the internal data structures of priority queue
            PriorityQueue<TKey, TValue>.emptyKeys = new TKey[0];
            PriorityQueue<TKey, TValue>.emptyValues = new TValue[0];
        }

        /// <summary>Initializes a new instance of the <see cref="T:Scheduler.Generic.PriorityQueue"></see> class that is empty, 
        /// <para>has the default initial capacity, and uses the default <see cref="T:System.Collections.Generic.IComparer"></see>.</para>
        /// </summary>
        public PriorityQueue()
        {
            this._keys = PriorityQueue<TKey, TValue>.emptyKeys;
            this._array = PriorityQueue<TKey, TValue>.emptyValues;
            this._size = 0;
            // create the default comparer for the empty queue
            this.comparer = System.Collections.Generic.Comparer<TKey>.Default;
        }

        /// <summary>Initializes a new instance of the <see cref="T:Scheduler.Generic.PriorityQueue"></see> class that contains elements copied from the specified collection
        /// <para>and has sufficient capacity to accommodate the number of elements copied.</para></summary>
        /// <param name="collection">The collection whose elements are copied to the new <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</param>
        /// <exception cref="T:System.ArgumentNullException">collection is null.</exception>
        public PriorityQueue(IEnumerable<KeyValuePair<TKey, TValue>> collection)
            : this()
        {
            if (comparer != null)
            {
                this.comparer = System.Collections.Generic.Comparer<TKey>.Default;
            }

            if (collection == null)
            {
                throw new ArgumentNullException(collection.ToString());
            }

            // initial dimension of the value array = 4 (it may be any number)
            this._array = new TValue[4];
            this._size = 0;
            this._version = 0;
            using (IEnumerator<KeyValuePair<TKey, TValue>> enumerator1 = collection.GetEnumerator())
            {
                while (enumerator1.MoveNext())
                {
                    // enqueue the supplied values with their keys
                    this.Enqueue(enumerator1.Current.Value, enumerator1.Current.Key);
                }
            }
        }

        /// <summary>Initializes a new instance of the <see cref="T:Scheduler.Generic.PriorityQueue"></see> class that is empty and has the specified initial capacity.</summary>
        /// <param name="capacity">The initial number of elements that the <see cref="T:Scheduler.Generic.PriorityQueue"></see> can contain.</param>
        /// <exception cref="T:System.ArgumentOutOfRangeException">capacity is less than zero.</exception>
        public PriorityQueue(int capacity)
        {
            if (capacity < 0)
            {
                throw new ArgumentOutOfRangeException(capacity.ToString(), "Non negative number required !");
            }

            this._array = new TValue[capacity];
            this._keys = new TKey[capacity];
            this._head = 0;
            this._tail = 0;
            this._size = 0;

            this.comparer = System.Collections.Generic.Comparer<TKey>.Default;

        }

        /// <summary>Initializes a new instance of the <see cref="T:Scheduler.Generic.PriorityQueue"></see> class that is empty, has the specified initial capacity, and uses the specified <see cref="T:System.Collections.Generic.IComparer"></see>.</summary>
        /// <param name="capacity">The initial number of elements that the <see cref="T:Scheduler.Generic.PriorityQueue"></see> can contain.</param>
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IComparer"></see> implementation to use when comparing keys.-or-null to use the default <see cref="T:System.Collections.Generic.Comparer"></see> for the type of the key.</param>
        /// <exception cref="T:System.ArgumentOutOfRangeException">capacity is less than zero.</exception>
        public PriorityQueue(int capacity, IComparer<TKey> comparer)
            : this(comparer)
        {
            this._array = new TValue[capacity];
            this._keys = new TKey[capacity];
            this._head = 0;
            this._tail = 0;
            this._size = 0;
        }

        /// <summary>Initializes a new instance of the <see cref="T:Scheduler.Generic.PriorityQueue"></see> class that is empty, has the default initial capacity, and uses the specified <see cref="T:System.Collections.Generic.IComparer"></see>.</summary>
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IComparer`1"></see> implementation to use when comparing keys.-or-null to use the default <see cref="T:System.Collections.Generic.Comparer"></see> for the type of the key.</param>
        public PriorityQueue(IComparer<TKey> comparer)
        {
            this.comparer = comparer;
        }

        #endregion

        #region Public Fields

        /// <summary>Adds an object to the end of the <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</summary>
        /// <param name="item1">The object to add to the <see cref="T:Scheduler.Generic.PriorityQueue"></see>. The value can be null for reference types.</param>
        /// <param name="item2">The key to add to the <see cref="T:Scheduler.Generic.PriorityQueue"></see>. The value can't be null</param>
        public void Enqueue(TValue item1, TKey item2)
        {

            if (this._size == this._array.Length)
            {
                int num1 = (int)((this._array.Length * 200) / ((long)100));
                if (num1 < (this._array.Length +4))
                {
                    num1 = this._array.Length + 4;
                }
                // resize the capacity
                this.SetCapacity(num1);
            } 
            // insert the element in the priority queue's internal data structure and sort them
            this.InsertElement(item1, item2);
            this._size++;
            this._version++;
        }

        /// <summary>Removes and returns the object at the beginning of the <see cref="T:Scheduler.Generic.PriorityQueue"></see> It is the object of highest priority.</summary>
        /// <returns>The object that is removed from the beginning of the <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</returns>
        /// <exception cref="T:System.InvalidOperationException">The <see cref="T:Scheduler.Generic.PriorityQueue"></see> is empty.</exception>
        public KeyValuePair<TKey, TValue> Dequeue()
        {
            KeyValuePair<TKey, TValue> keyvaluePair;
              keyvaluePair = DequeueMin();
              while (true)
              {
                  if (keyvaluePair.Value == null)
                  {
                      keyvaluePair = DequeueMin();
                  }
                  else
                      break;
              }
            return keyvaluePair;
        }
        private KeyValuePair<TKey, TValue> DequeueMin()
        {
            if (this._size == 0)
            {
                throw new InvalidOperationException("Queue is Empty !");
            }
            TValue local1 = this._array[this._head];
            TKey local2 = this._keys[this._head];
            // remove the element at the head (it has the element of highest priority)
            this._array[this._head] = default(TValue);
            // remove the corresponding key
            this._keys[this._head] = default(TKey);
            // sort the value array using the key array
            Array.Sort(this._keys, this._array, this.comparer);
            // reverse the array as it made the array in ascending order (lowest priority at the head)
            if (!sortl2h)
            {
                Array.Reverse(this._array);
                // correspondingly reverse the key array
                Array.Reverse(this._keys);
            }
            this._head = this.Head;
            this._size--;
            this._version++;
            KeyValuePair<TKey, TValue> keyvaluePair = new KeyValuePair<TKey, TValue>(local2, local1);
            return keyvaluePair;
        }

        /// <summary>Removes all objects from the <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</summary>
        /// <filterpriority>1</filterpriority>
        public void Clear()
        {
            if (this._head < this._tail)
            {
                Array.Clear(this._array, this._head, this._size);
            }
            else
            {
                Array.Clear(this._array, this._head, this._array.Length - this._head);
                Array.Clear(this._array, 0, this._tail);
            }
            this._head = 0;
            this._tail = 0;
            this._size = 0;
            this._version++;
        }

        /// <summary>Determines whether an element is in the <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</summary>
        /// <returns>true if item is found in the <see cref="T:Scheduler.Generic.PriorityQueue"></see>; otherwise, false.</returns>
        /// <param name="item">The object to locate in the <see cref="T:Scheduler.Generic.PriorityQueue"></see>. The value can be null for reference types.</param>
        public bool Contains(TValue item)
        {
            int num1 = this._head;
            int num2 = this._size;
            EqualityComparer<TValue> comparer1 = EqualityComparer<TValue>.Default;
            while (num2-- > 0)
            {
                if (item == null)
                {
                    if (this._array[num1] == null)
                    {
                        return true;
                    }
                }
                else if ((this._array[num1] != null) && comparer1.Equals(this._array[num1], item))
                {
                    return true;
                }
                num1 = (num1 + 1) % this._array.Length;
            }
            return false;
        }

        /// <summary>Copies the <see cref="T:Scheduler.Generic.PriorityQueue"></see> elements to an existing one-dimensional <see cref="T:System.Array"></see>, starting at the specified array index.</summary>
        /// <param name="array">The one-dimensional <see cref="T:System.Array"></see> that is the destination of the elements copied from <see cref="T:Scheduler.Generic.PriorityQueue"></see>. The <see cref="T:System.Array"></see> must have zero-based indexing.</param>
        /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
        /// <exception cref="T:System.ArgumentOutOfRangeException">index is less than zero.</exception>
        /// <exception cref="T:System.ArgumentNullException">array is null.</exception>
        /// <exception cref="T:System.ArgumentException">index is equal to or greater than the length of array.-or-The number of elements in the source <see cref="T:Scheduler.Generic.PriorityQueue"></see> is greater than the available space from index to the end of the destination array.</exception>
        public void CopyTo(TValue[] array, int arrayIndex)
        {
            if (array == null)
            {
                throw new ArgumentNullException(array.ToString(), "Array is not initialized !");
            }
            if ((arrayIndex < 0) || (arrayIndex > array.Length))
            {
                throw new ArgumentOutOfRangeException(array.ToString());
            }
            int num1 = array.Length;
            if ((num1 - arrayIndex) < this._size)
            {
                throw new ArgumentException("InvalidOffLen");
            }
            int num2 = ((num1 - arrayIndex) < this._size) ? (num1 - arrayIndex) : this._size;
            Array.Sort<TKey, TValue>(this._keys, this._array, this.comparer);
            if (num2 != 0)
            {
                int num3 = ((this._array.Length - this._head) < num2) ? (this._array.Length - this._head) : num2;
                Array.Copy(this._array, this._head, array, arrayIndex, num3);
                num2 -= num3;
                if (num2 > 0)
                {
                    Array.Copy(this._array, 0, array, (arrayIndex + this._array.Length) - this._head, num2);
                }
            }
        }

        /// <summary>Copies the <see cref="T:Scheduler.Generic.PriorityQueue"></see> elements to a new array.</summary>
        /// <returns>A new array containing elements copied from the <see cref="T:Scheduler.Generic.PriorityQueue"></see> The elements are sorted obviously.</returns>
        public TValue[] ToArray()
        {
            TValue[] localArray1 = new TValue[this._size];
            if (this._size != 0)
            {
                if (this._head < this._tail)
                {
                    Array.Copy(this._array, this._head, localArray1, 0, this._size);
                    return localArray1;
                }
                Array.Copy(this._array, this._head, localArray1, 0, this._array.Length - this._head);
                Array.Copy(this._array, 0, localArray1, this._array.Length - this._head, this._tail);
            }
            return localArray1;
        }

        /// <summary>Returns the object at the beginning of the <see cref="Scheduler.Generic.PriorityQueue"></see> without removing it. The object is of Highest priority</summary>
        /// <returns>The object at the beginning of the <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</returns>
        /// <exception cref="T:System.InvalidOperationException">The <see cref="T:Scheduler.Generic.PriorityQueue"></see> is empty.</exception>
        public KeyValuePair<TKey, TValue> Peek()
        {
            if (this._size == 0)
            {
                throw new InvalidOperationException("Empty Queue");
            }
            TValue val = this._array[(this.Head)];
            TKey key = this._keys[(this.Head)];
            KeyValuePair<TKey, TValue> ret = new KeyValuePair<TKey, TValue>(key, val);
            return ret;
        }

        /// <summary>Gets the <see cref="T:System.Collections.Generic.IComparer"></see> for the <see cref="T:Scheduler.Generic.PriorityQueue"></see>. </summary>
        /// <returns>The <see cref="T:System.IComparable"></see> for the current <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</returns>
        public IComparer<TKey> Comparer
        {
            get
            {
                return this.comparer;
            }
        }

        /// <summary>Sets the capacity to the actual number of elements in the <see cref="Scheduler.Generic.PriorityQueue"></see>, if that number is less than 90 percent of current capacity.
        /// </summary>
        public void TrimExcess()
        {
            int num1 = (int)(this._array.Length * 0.9);
            if (this._size < num1)
            {
                this.SetCapacity(this._size);
            }
        }

        /// <summary>Gets the number of elements contained in the <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</summary>
        /// <returns>The number of elements contained in the <see cref="T:Scheduler.Generic.PriorityQueue"></see>.</returns>
        public int Count
        {
            get
            {
                return this._size;
            }
        }

        #endregion

        #region Private Methods

        // Returns the index of the element with the key given.
        public int IndexOfKey(TKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(key.ToString());
            }

            int num1 = Array.IndexOf<TKey>(this._keys, key, 0);
            if (num1 < 0)
            {
                return -1;
            }
            return num1;

        }

        // Returns the index of the element given.
        internal int IndexOfValue(TValue value)
        {
            return Array.IndexOf<TValue>(this._array, value, 0, this._size);
        }

        // Returns the object of corresponding index
        internal KeyValuePair<TKey, TValue> GetElement(int i)
        {
            TValue val = this._array[(this._head + i) % this._array.Length];
            TKey key = this._keys[(this._head + i) % this._array.Length];
            KeyValuePair<TKey, TValue> ret = new KeyValuePair<TKey, TValue>(key, val);
            return ret;
        }

        // Reallocate memory to re-dimension the queue with given capacity.
        private void SetCapacity(int capacity)
        {
            TValue[] localArray1 = new TValue[capacity];
            TKey[] localArray2 = new TKey[capacity];
            if (this._size > 0)
            {
                if (this._head < this._tail)
                {
                    Array.Copy(this._array, this._head, localArray1, 0, this._size);
                    Array.Copy(this._keys, this._head, localArray2, 0, this._size);
                }
                else
                {
                    Array.Copy(this._array, this._head, localArray1, 0, this._array.Length - this._head);
                    Array.Copy(this._array, 0, localArray1, this._array.Length - this._head, this._tail);

                    Array.Copy(this._keys, this._head, localArray2, 0, this._keys.Length - this._head);
                    Array.Copy(this._keys, 0, localArray2, this._keys.Length - this._head, this._tail);
                }
            }
            this._array = localArray1;
            this._keys = localArray2;
            this._head = 0;
            this._tail = this._size;
            this._version++;
        }

        /// <summary>
        /// Insert the element in the internal data structure of the priority queue
        /// </summary>
        /// <param name="value"> value to be entered</param>
        /// <param name="key"> corresponding key of the value</param>
        private void InsertElement(TValue value, TKey key)
        {
            TKey[] tempkey = new TKey[this._keys.Length];
            TValue[] tempvalue = new TValue[this._keys.Length];
            int count = 0;

            for (int i = 0; i < this._size; i++)
            {
                tempkey[count] = this._keys[i];
                tempvalue[count] = this._array[i];
                count++;
            }
            tempkey[count] = key;
            tempvalue[count] = value;
            Array.Copy(tempkey, this._keys, this._keys.Length);
            Array.Copy(tempvalue, this._array, this._array.Length);
            Array.Sort(this._keys, this._array);
            if (!sortl2h)
            {
                Array.Reverse(this._keys);
                Array.Reverse(this._array);
            }
            this._head = this.Head;

        }

        private TKey MaximumKey()
        {
            TKey max = default(TKey);
            for (int i = 0; i < this._keys.Length; i++)
            {
                if (Comparer<TKey>.Default.Compare(this._keys[i], max) > 0)
                {
                    max = this._keys[i];
                }
            }
            return max;
        }
        private TKey MinKey()
        {
            TKey min = default(TKey);
            for (int i = 0; i < this._keys.Length; i++)
            {
                if (Comparer<TKey>.Default.Compare(this._keys[i], min) < 0)
                {
                    min = this._keys[i];
                }
            }
            return min;
        }

        private int Head
        {
            get { return this.IndexOfKey(this.MaximumKey()); }
            //get { return this.IndexOfKey(this.MinKey()); }
        }
        private int Tail
        {
            get { return this.IndexOfKey(this.MinKey()); }
            //get { return this.IndexOfKey(this.MinKey()); }
        }
        #endregion

        #region Interface Implementation

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return new PriorityQueue<TKey, TValue>.Enumerator<TKey, TValue>(this, 1);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new PriorityQueue<TKey, TValue>.Enumerator<TKey, TValue>(this, 1);
        }

        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
        {
            return new PriorityQueue<TKey, TValue>.Enumerator<TKey, TValue>(this, 1);
        }

        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            if (array == null)
            {
                throw new ArgumentNullException(array.ToString());
            }
            int num1 = array.Length;
            if ((arrayIndex < 0) || (arrayIndex > num1))
            {
                throw new ArgumentOutOfRangeException(arrayIndex.ToString(), "Need non negative number");
            }
            if ((num1 - arrayIndex) < this.Count)
            {
                throw new ArgumentException("Offset is too small", array.ToString());
            }
            if (array.GetLowerBound(0) != 0)
            {
                throw new ArgumentException("Non zero lower bound");
            }

            for (int num2 = 0; num2 < this.Count; num1++)
            {
                KeyValuePair<TKey, TValue> pair1 = new KeyValuePair<TKey, TValue>(this._keys[num2], this._array[num2]);
                array[arrayIndex + num2] = pair1;
            }

        }

        bool ICollection.IsSynchronized
        {
            get
            {
                return false;
            }
        }

        object ICollection.SyncRoot
        {
            get
            {
                if (this._syncRoot == null)
                {
                    Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
                }
                return this._syncRoot;
            }
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
        {
            int num1 = this.IndexOfKey(keyValuePair.Key);
            if ((num1 >= 0) && EqualityComparer<TValue>.Default.Equals(this._array[num1], keyValuePair.Value))
            {
                return true;
            }
            return false;
        }

        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
        {
            this.Enqueue(keyValuePair.Value, keyValuePair.Key);
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair)
        {
            int num1 = this.IndexOfKey(keyValuePair.Key);
            if ((num1 >= 0) && EqualityComparer<TValue>.Default.Equals(this._array[num1], keyValuePair.Value))
            {
                this.Dequeue();
                return true;
            }
            return false;
        }

        int ICollection<KeyValuePair<TKey, TValue>>.Count
        {
            get { return this.Count; }
        }

        void ICollection.CopyTo(Array array, int arrayIndex)
        {
            if (array == null)
            {
                throw new ArgumentNullException(array.ToString());
            }
            if (array.Rank != 1)
            {
                throw new ArgumentException("Multidimension is not supported");
            }
            if (array.GetLowerBound(0) != 0)
            {
                throw new ArgumentException("Non zero lower bound");
            }
            if ((arrayIndex < 0) || (arrayIndex > array.Length))
            {
                throw new ArgumentOutOfRangeException(arrayIndex.ToString(), "Non negative number needed");
            }
            if ((array.Length - arrayIndex) < this.Count)
            {
                throw new ArgumentException("Offset too small");
            }

            KeyValuePair<TKey, TValue>[] pairArray1 = array as KeyValuePair<TKey, TValue>[];
            if (pairArray1 != null)
            {
                for (int num1 = 0; num1 < this.Count; num1++)
                {
                    pairArray1[num1 + arrayIndex] = new KeyValuePair<TKey, TValue>(this._keys[num1], this._array[num1]);
                }
            }
            else
            {
                object[] objArray1 = array as object[];
                if (objArray1 == null)
                {
                    throw new ArgumentException("Invalid array type");
                }
                try
                {
                    for (int num2 = 0; num2 < this.Count; num2++)
                    {
                        objArray1[num2 + arrayIndex] = new KeyValuePair<TKey, TValue>(this._keys[num2], this._array[num2]);
                    }
                }
                catch (ArrayTypeMismatchException)
                {
                    throw new ArgumentException("Invalid array type");
                }
            }
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
        {
            get
            {
                return false;
            }
        }

        int ICollection.Count
        {
            get { return this.Count; }
        }

        #endregion

        #region Declaration

        private TValue[] _array;
        private TKey[] _keys;
        private static TKey[] emptyKeys;
        private static TValue[] emptyValues;
        private IComparer<TKey> comparer;
        private int _head;
        private int _size;


        [NonSerialized]
        private object _syncRoot;
        private int _tail;
        private int _version;

        #endregion

        #region Enumerator Implementation

        [Serializable, StructLayout(LayoutKind.Sequential)]
        private struct Enumerator<Tkey, Tvalue> : IEnumerator<KeyValuePair<TKey, TValue>>, IDisposable, IEnumerator
        {
            internal const int KeyValuePair = 1;
            internal const int DictEntry = 2;
            private PriorityQueue<TKey, TValue> _priorityQueue;
            private TKey key;
            private TValue value;
            private int index;
            private int version;
            private int getEnumeratorRetType;

            internal Enumerator(PriorityQueue<TKey, TValue> priorityQueue, int getEnumeratorRetType)
            {
                this._priorityQueue = priorityQueue;
                this.index = 0;
                this.version = this._priorityQueue._version;
                this.getEnumeratorRetType = getEnumeratorRetType;
                this.key = default(TKey);
                this.value = default(TValue);
            }

            public void Dispose()
            {
                this.index = 0;
                this.key = default(TKey);
                this.value = default(TValue);
            }

            public bool MoveNext()
            {
                if (this.version != this._priorityQueue._version)
                {
                    throw new InvalidOperationException("Enumeration failed !");
                }
                if (this.index < this._priorityQueue.Count)
                {
                    this.key = this._priorityQueue._keys[this.index];
                    this.value = this._priorityQueue._array[this.index];
                    this.index++;
                    return true;
                }
                this.index = this._priorityQueue.Count + 1;
                this.key = default(TKey);
                this.value = default(TValue);
                return false;
            }

            public KeyValuePair<TKey, TValue> Current
            {
                get
                {
                    return new KeyValuePair<TKey, TValue>(this.key, this.value);
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    if ((this.index == 0) || (this.index == (this._priorityQueue.Count + 1)))
                    {
                        throw new InvalidOperationException("Enumeration operation cannot happen !");
                    }
                    if (this.getEnumeratorRetType == 2)
                    {
                        return new DictionaryEntry(this.key, this.value);
                    }
                    return new KeyValuePair<TKey, TValue>(this.key, this.value);
                }
            }

            void IEnumerator.Reset()
            {
                if (this.version != this._priorityQueue._version)
                {
                    throw new InvalidOperationException("Enumeration failed !");
                }
                this.index = 0;
                this.key = default(TKey);
                this.value = default(TValue);
            }

        }

        #endregion

    }
}
